﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace M3G {
    public class RenderTarget : Object3D {
        #region Field
        ImageBase target;
        int       miplevel;
        int       face;
        #endregion

        #region Method
        public RenderTarget (Image2D target, int miplevel) {
            if (target == null) {
                throw new ArgumentNullException ("Target is null");
            }
            if (miplevel != 0 && target.Mipmapped == false) {
                throw new ArgumentException ("Mipmap level was specified, but target is not mipmapped");
            }
            var w = target.Width;
            var h = target.Height;
            if (miplevel != 0 && (((w & (w - 1)) != 0 || (h & (h - 1)) != 0))) {
                throw new ArgumentException ("Mipmap level was specified, but target dimension is not power of 2, w=" + w + ",h=" + h);
            }
            var mipmax = Math.Log (Math.Max (w, h), 2.0);
            if (miplevel < 0 || miplevel > mipmax) {
                throw new ArgumentException ("Invalid miplevel, it must be within [0," + mipmax + "]");
            }

            this.target = target;
            this.miplevel = miplevel;
            this.face = 0;
        }


        public RenderTarget (ImageCube target, int face, int miplevel) {
            if (target == null) {
                throw new ArgumentNullException ("Target is null");
            }
            if (face < ImageCube.PosX || face > ImageCube.NegZ) {
                throw new ArgumentException ("Face must be one of symbolic constants defined in ImageCube, face=" + face);
            }
            if (miplevel != 0 && target.Mipmapped == false) {
                throw new ArgumentException ("Mipmap level was specified, but target is not mipmapped");
            }
            var w = target.Width;
            var h = target.Height;
            if (miplevel != 0 && (((w & (w - 1)) != 0 || (h & (h - 1)) != 0))) {
                throw new ArgumentException ("Mipmap level was specified, but target dimension is not power of 2, w=" + w + ",h=" + h);
            }
            var mipmax = Math.Log (Math.Max (w, h), 2.0);
            if (miplevel < 0 || miplevel > mipmax) {
                throw new ArgumentException ("Invalid miplevel, it must be within [0," + mipmax + "]");
            }

            this.target = target;
            this.miplevel = miplevel;
            this.face = face;

        }

        protected RenderTarget (RenderTarget renderTarget)
            : base (renderTarget) {
            this.target = renderTarget.target;
            this.miplevel = renderTarget.miplevel;
            this.face = renderTarget.face;
        }

        public ImageBase Target {
            get { return target; }
        }

        public int TargetFace {
            get { return face; }
        }

        public int TargetLevel {
            get { return miplevel; }
        }

        public override Object3D[] References {
            get {
                var q = new List<Object3D> ();
                q.AddRange (base.References);
                q.Add (target);
                q.RemoveAll (x => x == null);
                return q.ToArray ();
            }
        }

        public override Object3D Duplicate () {
            return new RenderTarget (this);
        }
        #endregion 
    }
}
